---
title: Systems Programming
---

Systems programming involves writing software that interacts directly with computer hardware and the operating system. C++ is a primary language for systems programming due to its low-level memory access, performance, and control over system resources. This module will cover fundamental concepts like file I/O, network programming, inter-process communication, and system calls, highlighting C++'s capabilities compared to JavaScript's higher-level abstractions.

## File I/O Operations

C++ provides robust mechanisms for file input and output through the `<fstream>` library. This allows programs to read from and write to files on the local filesystem.

*   `std::ifstream`: For reading from files.
*   `std::ofstream`: For writing to files.
*   `std::fstream`: For both reading and writing.

<UniversalEditor title="File I/O Comparison" compare={true}>
```javascript !! js
// JavaScript (Node.js): File I/O using fs module (asynchronous by default)
const fs = require('fs');

// Writing to a file
fs.writeFile('example.txt', 'Hello from JavaScript!', (err) => {
  if (err) throw err;
  console.log('File written successfully.');
});

// Reading from a file
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log('File content:', data);
});

// Synchronous version (less common in Node.js)
// try {
//   fs.writeFileSync('sync_example.txt', 'Synchronous write.');
//   const data = fs.readFileSync('sync_example.txt', 'utf8');
//   console.log('Sync file content:', data);
// } catch (err) {
//   console.error('Sync file error:', err);
// }
```

```cpp !! cpp
// C++: File I/O using <fstream>
#include <iostream>
#include <fstream> // For file stream operations
#include <string>

int main() {
  // Writing to a file
  std::ofstream outFile("example.txt"); // Open file for writing
  if (outFile.is_open()) {
    outFile << "Hello from C++!\n";
    outFile << "This is a new line.\n";
    outFile.close(); // Close the file
    // std::cout << "File written successfully." << std::endl;
  } else {
    // std::cerr << "Unable to open file for writing." << std::endl;
  }

  // Reading from a file
  std::ifstream inFile("example.txt"); // Open file for reading
  if (inFile.is_open()) {
    std::string line;
    // while (std::getline(inFile, line)) { // Read line by line
    //   std::cout << "File content: " << line << std::endl;
    // }
    inFile.close();
  } else {
    // std::cerr << "Unable to open file for reading." << std::endl;
  }

  return 0;
}
```
</UniversalEditor>

## Network Programming Basics

C++ provides low-level access to network sockets, enabling direct communication over networks. This is typically done using system-specific APIs (like Winsock on Windows or Berkeley sockets on Unix-like systems) or cross-platform libraries.

### Sockets

*   **Socket:** An endpoint for sending or receiving data across a computer network.
*   **Types:** Stream sockets (TCP) for reliable, connection-oriented communication; Datagram sockets (UDP) for unreliable, connectionless communication.

<UniversalEditor title="Basic Socket Programming (Conceptual)" compare={true}>
```javascript !! js
// JavaScript (Node.js): High-level network APIs (e.g., http, net modules)
const http = require('http');

// Simple HTTP server
// http.createServer((req, res) => {
//   res.writeHead(200, { 'Content-Type': 'text/plain' });
//   res.end('Hello World\n');
// }).listen(3000, '127.0.0.1', () => {
//   console.log('Server running at http://127.0.0.1:3000/');
// });

// Simple HTTP client
// http.get('http://127.0.0.1:3000', (res) => {
//   let data = '';
//   res.on('data', (chunk) => { data += chunk; });
//   res.on('end', () => { console.log('Client received:', data); });
// }).on('error', (e) => { console.error(`Got error: ${e.message}`); });
```

```cpp !! cpp
// C++: Basic Socket Programming (Conceptual - requires platform-specific headers)
// This example is highly simplified and conceptual. Real-world socket programming
// involves more error handling, setup, and platform-specific details.

// #include <iostream>
// #include <string>
// #include <sys/socket.h> // For socket, connect, send, recv (Unix-like)
// #include <arpa/inet.h>  // For inet_addr (Unix-like)
// #include <unistd.h>   // For close (Unix-like)

// int main() {
//   // Create socket
//   int sock = socket(AF_INET, SOCK_STREAM, 0);
//   if (sock == -1) { /* std::cerr << "Could not create socket" << std::endl; */ return 1; }

//   // Prepare the sockaddr_in structure
//   sockaddr_in server;
//   server.sin_addr.s_addr = inet_addr("127.0.0.1");
//   server.sin_family = AF_INET;
//   server.sin_port = htons(8888);

//   // Connect to remote server
//   if (connect(sock, (sockaddr*)&server, sizeof(server)) < 0) {
//     // std::cerr << "Connect error" << std::endl; return 1;
//   }
//   // std::cout << "Connected" << std::endl;

//   // Send some data
//   std::string message = "Hello from C++ client!";
//   if (send(sock, message.c_str(), message.length(), 0) < 0) {
//     // std::cerr << "Send failed" << std::endl; return 1;
//   }
//   // std::cout << "Data Send\n" << std::endl;

//   // Receive a reply from the server
//   char server_reply[2000];
//   if (recv(sock, server_reply, 2000, 0) < 0) {
//     // std::cerr << "Recv failed" << std::endl;
//   }
//   // std::cout << "Reply received\n" << server_reply << std::endl;

//   close(sock);
//   return 0;
// }
```
</UniversalEditor>

## Inter-Process Communication (IPC)

IPC mechanisms allow different processes to communicate and synchronize their actions. C++ can utilize various OS-level IPC methods.

*   **Pipes:** Unidirectional communication channels between related processes.
*   **Shared Memory:** Fastest IPC, allowing processes to directly access a common region of memory.
*   **Message Queues:** Processes exchange messages through a system queue.
*   **Semaphores:** Synchronization primitives used to control access to shared resources.
*   **Sockets:** Can also be used for IPC between unrelated processes, even on different machines.

## System Call Interfaces

C++ programs can directly invoke **system calls** to request services from the operating system kernel. These calls provide access to low-level functionalities like file system operations, process management, and network communication.

*   **`open()`, `read()`, `write()`, `close()`:** Low-level file operations.
*   **`fork()`, `exec()`, `wait()`:** Process creation and management.
*   **`socket()`, `bind()`, `listen()`, `accept()`, `connect()`:** Network socket operations.

## Cross-Platform Development Considerations

While C++ offers low-level control, systems programming often involves platform-specific APIs. To write cross-platform code, developers typically use:

*   **Standard C++ Library:** Provides platform-independent features (e.g., `std::thread`, `std::filesystem` (C++17)).
*   **Cross-Platform Libraries:** Libraries like Boost.Asio (networking), Qt (GUI, networking, file system), or POCO C++ Libraries abstract away OS differences.
*   **Conditional Compilation:** Using preprocessor directives (`#ifdef`, `#ifndef`) to include platform-specific code.

## Low-Level Memory Operations

C++ allows direct manipulation of memory through pointers, enabling highly optimized and specialized memory operations. This includes:

*   **Raw Memory Allocation:** `malloc`/`free` (from C) or `new`/`delete`.
*   **Placement New:** Constructing an object at a pre-allocated memory location.
*   **Bit Manipulation:** Directly manipulating individual bits within data types.
*   **Memory Mapping:** Mapping files or devices directly into a process's address space.

<UniversalEditor title="Low-Level Memory Operations (Conceptual)" compare={true}>
```javascript !! js
// JavaScript: No direct low-level memory access.
// Memory is managed by the garbage collector.
// ArrayBuffer and TypedArrays provide binary data manipulation,
// but not direct memory addresses.
const buffer = new ArrayBuffer(16); // 16 bytes
const view = new DataView(buffer);

view.setInt32(0, 12345, true); // Write 32-bit integer at offset 0
console.log(view.getInt32(0, true)); // Read it back
```

```cpp !! cpp
// C++: Low-Level Memory Operations
#include <iostream>
#include <cstring> // For memcpy

int main() {
  // Raw memory allocation and manipulation
  char* buffer = new char[10]; // Allocate 10 bytes
  // std::memset(buffer, 0, 10); // Initialize to zeros

  int value = 12345;
  // std::memcpy(buffer, &value, sizeof(int)); // Copy bytes of int into buffer

  // int retrieved_value;
  // std::memcpy(&retrieved_value, buffer, sizeof(int)); // Copy bytes back to int
  // std::cout << "Retrieved value: " << retrieved_value << std::endl;

  delete[] buffer; // Deallocate

  // Bit manipulation
  unsigned char flags = 0b00001101; // Example flags: 8, 4, 1 are set
  // std::cout << "Flags: " << (int)flags << std::endl;
  // if (flags & (1 << 2)) { // Check if 3rd bit (value 4) is set
  //   std::cout << "Third bit is set." << std::endl;
  // }

  return 0;
}
```
</UniversalEditor>

## Comparison with JavaScript Systems Programming

JavaScript, particularly in browser environments, is highly sandboxed and has very limited direct access to the underlying operating system or hardware. Node.js extends JavaScript's capabilities to the server-side, providing APIs for file system access, networking, and process management, but these are typically high-level abstractions built on top of C++ or C code.

| Feature           | JavaScript (Node.js)                     | C++                                      |
| :---------------- | :--------------------------------------- | :--------------------------------------- |
| **File I/O**      | High-level `fs` module (async/sync)      | Low-level `open`/`read`/`write`, `fstream` |
| **Networking**    | High-level `net`, `http` modules         | Low-level sockets (platform-specific APIs) |
| **IPC**           | Child processes, message passing         | Pipes, shared memory, message queues, sockets |
| **System Calls**  | Indirectly via Node.js runtime           | Direct invocation via C/C++ libraries    |
| **Memory Access** | Managed by GC, `ArrayBuffer` for binary data | Direct pointer manipulation, manual allocation |
| **Performance**   | Good for I/O-bound, less for CPU-bound   | Excellent for CPU-bound, low-latency, direct hardware interaction |

C++ is the language of choice for operating systems, embedded systems, device drivers, and high-performance server applications where direct hardware interaction, precise memory control, and maximum performance are paramount. JavaScript, even with Node.js, operates at a higher level of abstraction, prioritizing developer productivity and safety over raw system control.

---

### Practice Questions:
1.  Describe the difference between high-level file I/O (like `std::ofstream`) and low-level file I/O (like `open`/`read`/`write` system calls) in C++. When would you choose one over the other?
2.  Explain the concept of a socket in network programming. How does C++'s approach to network programming differ from JavaScript's (e.g., in Node.js)?
3.  What are system calls, and why are they important in systems programming? Provide an example of a task that would typically require a system call.

### Project Idea:
*   Implement a simple command-line utility in C++ that copies the content of one file to another. Your program should take two command-line arguments: source file path and destination file path. Use `std::ifstream` and `std::ofstream` for file operations. Add error handling for cases like file not found or inability to write to the destination. For an advanced challenge, try implementing it using low-level `open`, `read`, and `write` system calls.
